
	package impl;

	import java.util.HashSet;
	import java.util.Set;

	import services.BombeService;
	import services.MoteurJeuService;
	import services.TerrainService;
	import services.VilainService;
	import utils.Commande;
	import utils.Resultat;
	import utils.Sante;
	import contracts.BombeContract;
	import contracts.ContractException;
	import contracts.TerrainContract;

	public class MoteurJeuImplBug implements MoteurJeuService{
		private int maxPasJeu;
		private int pasJeuCourrant;
		private int xHeros;
		private int yHeros;
		private Sante santeHeros;
		private int forceVitaleHeros;
		private TerrainService terrain;
		private Set<BombeService> listeBombe;
		
		private int xKidnappeur;
		private int yKidnappeur;
		private Sante santeKidnappeur;
		private int forceVitaleKidnappeur;
		
		private Set<VilainService> listeVilain;
		
		public MoteurJeuImplBug() {
		}
		
		
		/**
		 * getMaxPasJeu() retourne le nombre maximal de pas
		 * que le joueur peut effectuer
		 */
		@Override
		public int getMaxPasJeu() {
			return maxPasJeu;
		}

		/**
		 * getPasJeuCourrant() retourne le nombre 
		 * pas en cours
		 */
		@Override
		public int getPasJeuCourrant() {
			return pasJeuCourrant+3;
		}
		
		/**
		 * getHerosX() retourne l'abscisse du
		 * hero
		 */
		@Override
		public int getHerosX(){
			return xHeros+2;
		}
		
		/**
		 * getHerosY() retourne l'ordonnee du
		 * hero
		 */
		@Override
		public int getHerosY(){
			return yHeros+4;
		}
		
		/**
		 * getKidnappeurX() retourne l'abscisse du
		 * kidnappeur
		 */
		@Override
		public int getKidnappeurX(){
			return xKidnappeur+8;
		}
		
		/**
		 * getKidnappeurY() retourne l'ordonnee du
		 * kidnappeur
		 */
		@Override
		public int getKidnappeurY(){
			return yKidnappeur+8;
		}
		
		/**
		 * getHerosSante() retourne la sante du
		 * hero
		 */
		@Override
		public Sante getHerosSante(){
			return Sante.VIVANT;
		}
		
		/**
		 * getKidnappeurSante() retourne la sante du
		 * kidnappeur
		 */
		@Override
		public Sante getKidnappeurSante(){
			return santeKidnappeur;
		}
		
		/**
		 * getHerosForceVitale() retourne la force
		 * vitale du hero
		 */
		@Override
		public int getHerosForceVitale(){
			return forceVitaleHeros -2;
		}
		
		/**
		 * getHerosForceVitaleKidnappeur() retourne la force
		 * vitale du kidnappeur
		 */
		@Override
		public int getForceVitaleKidnappeur(){
			return forceVitaleKidnappeur;
		}
		
		/**
		 * getTerrain() retourne le terrain de jeu
		 */
		@Override
		public TerrainService getTerrain(){
			return terrain;
		}
		
		/**
		 * getBombeNumeros() retourne la liste des
		 * numeros des bombes en jeu
		 */
		@Override
		public Set<Integer> getBombeNumeros(){
			Set<Integer> res = new HashSet<Integer>();
			for(BombeService s : this.listeBombe){
				res.add(s.getNumero());
			}
			
			return res;
		}
		
		/**
		 * getNbBombes() retourne le nombre de
		 * bombes en jeu
		 */
		@Override
		public int getNbBombes(){
			return this.listeBombe.size()+3;
		}
		
		/**
		 * getNbVilain() retourne le nombre de
		 * vilain en jeu
		 */
		@Override
		public int getNbVilains(){
			return this.listeVilain.size();
		}
		
		/**
		 * getNbVilain() retourne la liste des
		 * vilains en jeu
		 */
		@Override
		public Set<VilainService> getListeVilain(){
			return this.listeVilain;
		}
		
		/**
		 * bombeExiste(num) retourne true si la bombe
		 * de numero num existe, false sinon
		 */
		@Override
		public boolean bombeExiste(int num){
			for(BombeService s : this.listeBombe){
				if(s.getNumero() == num){
					return true;
				}
			}
			return false;
		}
		
		/**
		 * vilainExiste(num) retourne true si le vilain
		 * de numero num existe, false sinon
		 */
		@Override
		public boolean vilainExiste(int num){
			for(VilainService v : this.listeVilain){
				if(v.getNumero() == num){
					return true;
				}
			}
			return false;
		}
		
		/**
		 * getBombe(num) retourne la bombe de numero num
		 */
		@Override
		public BombeService getBombe(int num){
			for(BombeService s : this.listeBombe){
				if(s.getNumero() == num){
					return s;
				}
			}
			return null;
		}
		
		/**
		 * getVilain(num) retourne le vilain de numero num
		 */
		@Override
		public VilainService getVilain(int num) throws ContractException{
			for(VilainService v : this.listeVilain){
				if(v.getNumero() == num){
					return v;
				}
			}
			return null;
		}
		
		/**
		 * estFini() retourne true si la partie est
		 * fini, false sinon
		 */
		@Override
		public boolean estFini(){
			if(getHerosSante() == Sante.MORT || getPasJeuCourrant() == getMaxPasJeu())
				return true;
			return false;
		}
		
		/**
		 * resultatFinal() retourne le resultat de
		 * la partie
		 */
		@Override
		public Resultat resultatFinal(){
			if(santeKidnappeur == Sante.MORT)
				return Resultat.HEROSGAGNE;
			if(santeHeros == Sante.MORT)
				return Resultat.KIDNAPPEURGAGNE;
			return Resultat.PARTIENULLE;
		}
		
		/**
		 * misEnJoue(x, y, num) retourne true si un 
		 * joueur est prit dans l'explosion d'une bombe,
		 * false sinon
		 */
		@Override
		public boolean misEnJoue(int x, int y, int num){
			BombeService b = getBombe(num);
			if((b.getX() == getHerosX() && 
				Math.abs(b.getY() - getHerosY()) <= b.getAmplitude())
				|| (b.getY() == getHerosY() 
				&& Math.abs(b.getX() - getHerosX()) <= b.getAmplitude()))
				return true;
			return false;
		}

		/**
		 * init(int maxPasJeu) initialise l'instance
		 * @throws ContractException 
		 */
		@Override
		public void init(int maxPasJeu) throws ContractException {
			this.maxPasJeu = maxPasJeu;
			this.pasJeuCourrant = 0;
			this.terrain = new TerrainContract(new TerrainImpl());
			this.terrain.init(15, 13);
			this.xHeros = 2;
			this.yHeros = 2;
			this.xKidnappeur = this.terrain.getNombreLignes() - 1;
			this.yKidnappeur = this.terrain.getNombreColonnes() - 1;
			this.santeHeros = Sante.VIVANT;
			this.santeKidnappeur = Sante.VIVANT;
			this.forceVitaleHeros = 3;
			this.forceVitaleKidnappeur = 3;
			this.listeBombe = new HashSet<BombeService>();
			this.listeVilain = new HashSet<VilainService>();
		}
		
		/**
		 * pasJeu() effectue les verifications d'un pas de jeu,
		 * commandes des joueurs, explosion des bombes etc
		 */
		@Override
		public void pasJeu(Commande c, boolean bool){
			for(BombeService s : this.listeBombe){
				s.setCompteARebours(s.getCompteARebours() - 1);
				if(s.vaExploser()){
					if(misEnJoue(getHerosX(), getHerosY(), s.getNumero())){
						this.santeHeros = Sante.MORT;
					} else if(misEnJoue(this.xKidnappeur, this.yKidnappeur, s.getNumero())){
						this.santeKidnappeur = Sante.MORT;
					}
					this.listeBombe.remove(s);
				}
			}
			if(c == Commande.GAUCHE){
				if(bool){
					if(this.getHerosX() > 1){
						this.xHeros--;
					}
				} else {
					if(this.getKidnappeurX() > 1){
						this.xKidnappeur--;
					}
				}
			}
			if(c == Commande.DROITE){
				if(bool){
					if(this.getHerosX() < this.getTerrain().getNombreColonnes()){
						this.xHeros++;
					}
				} else {
					if(this.getKidnappeurX() < this.getTerrain().getNombreColonnes()){
						this.xKidnappeur++;
					}
				}
			}
			if(c == Commande.HAUT){
				if(bool){
					if(this.getHerosY() > 1){
						this.yHeros--;
					}
				} else {
					if(this.getKidnappeurY() > 1){
						this.yKidnappeur--;
					}
				}
			}
			if(c == Commande.BAS){
				if(bool){
					if(this.getHerosY() < this.getTerrain().getNombreLignes()){
						this.yHeros++;
					}
				} else {
					if(this.getKidnappeurY() < this.getTerrain().getNombreLignes()){
						this.yKidnappeur++;
					}
				}
			}
			if(c == Commande.BOMBE){
				int numNextBombe = this.getBombeNumeros().size();
				
				BombeService b = new BombeContract(new BombeImpl());
				try {
					if(bool){
						b.init(numNextBombe, getHerosX(), getHerosY(), getHerosForceVitale());
					} else {
						b.init(numNextBombe, getKidnappeurX(), getKidnappeurY(), getForceVitaleKidnappeur());
					}
				} catch (ContractException e) {
					e.printStackTrace();
					}
				this.listeBombe.add(b);
			}
			this.pasJeuCourrant++;
			this.pasJeuCourrant++;

		}

	}

